package main

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"github.com/imroc/req"
	"github.com/widuu/gojson"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

var ctx = context.Background()
var GlobalClient *redis.Client

func initClient()(err error){
	GlobalClient = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // no password set
		DB:       0,  // use default DB
	})
	_,err = GlobalClient.Ping().Result()
	if err != nil {
		return err
	}
	fmt.Println("client start ")
	return nil

}
// WeatherData 存储某个区具体的天气数据
type WeatherData struct {
	Humidity    string `json:"humidity"`    // 湿度
	Temperature string `json:"temperature"` // 温度
	Skycon      string `json:"skycon"`      // 主要天气现象
	Pressure    string `json:"pressure"`    // 压强
	Direction   string `json:"direction"`   // 风向
	Speed       string `json:"speed"`       // 风速
	times 		time.Time `json:"times"`	// 时间
}

// WeatherCoordinates 该结构体的key值作为经纬度的坐标，value值作为对应的天气数据
type WeatherCoordinates struct {
	Coordinate  string      `json:"coordinate"`   // 坐标，经纬度
	WeatherData WeatherData `json:"weather_data"` // 天气数据
}

// Segmentation 返回两个字符串，分割过后的比如 123.456，456789 分割成 123.456 456789两个字符串
func Segmentation(strstr string, substr string) []string {
	temp := strstr
	comma := strings.Index(strstr, substr) + 1

	test := strings.LastIndex(temp, substr)

	var splies []string = []string{temp[0:test], strstr[comma:]}
	return splies
}

// MunicipalityRegion 对直辖市的行政区做特殊处理，因为只有一个城区不做循环处理
func MunicipalityRegion(ultimatelyMap map[string]string, i int, s string) {

	CountDistrict, _ := gojson.Json(s).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(1).Get("districts").ToArray()

	countyNumber := len(CountDistrict) / 5 // 计算直辖市有几个区

	for j := 1; j < countyNumber+1; j++ {
		AdministrativeNumber := gojson.Json(s).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(1).Get("districts").Getindex(j).Get("adcode").Tostring()
		LatitudeLongitude := gojson.Json(s).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(1).Get("districts").Getindex(j).Get("center").Tostring()
		// 获取到直辖市的每个区的行政号和经纬度中心点
		ultimatelyMap[AdministrativeNumber] = LatitudeLongitude

	}

}

// Provincial 调用高德地图接口将行政区号和经纬度导出到map中
func Provincial(ultimatelyMap map[string]string) {
	url := "https://restapi.amap.com/v3/config/district?parameters"
	pam := req.Param{
		"keywords":    "中国",
		"subdistrict": "3",
		"extensions":  "base",
		"key":         "423bfeb3ec3c1edaf179fabe2cb7be49",
	}
	// 请求高德地图的RUL和参数
	re, err := req.Get(url, pam)
	if err != nil {
		log.Fatal("req Get error")
	}

	// 全国有2800多个县级单位

	if err != nil {
		fmt.Println(err)
	}

	for i := 1; i < 35; i++ {
		// 全国有34个省级行政单位
		CountCity, _ := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").ToArray()
		// 计算一下一个省有多少个市 如果是直辖市就是一个市，但也是省级行政单位
		municipality := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("name").Tostring()
		if municipality == "台湾省" {
			// 该省在高德API没有下属县区的返回，做特殊处理
			// 四个直辖市由于只有一个城区，不做循环

			adcode := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("adcode").Tostring()
			center := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("center").Tostring()
			// 获取到台湾省的行政编号和中心坐标
			ultimatelyMap[adcode] = center
			continue
		} else if municipality == "北京市" {
			MunicipalityRegion(ultimatelyMap, i, re.String())
			continue
		} else if municipality == "上海市" {
			MunicipalityRegion(ultimatelyMap, i, re.String())
			continue
		} else if municipality == "天津市" {
			MunicipalityRegion(ultimatelyMap, i, re.String())
			continue
		}
		number := len(CountCity) / 5
		// 三个直辖市需要做特殊处理，因为都只有1个城区，除了重庆市，只有1个城区，j=1 number=1的情况下不会进入循环

		for j := 1; j < number+1; j++ {

			// CountDistrict, _ := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(j).Get("districts").ToArray()
			AdministrativeNumber1:= gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(j).Get("citycode").Tostring()
			LatitudeLongitude2 := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(j).Get("center").Tostring()
			ultimatelyMap[AdministrativeNumber1]=LatitudeLongitude2
			/*
			countyNumber := len(CountDistrict) / 5
			// 计算一下一个市有多少个区

			for a := 1; a < countyNumber+1; a++ {
				AdministrativeNumber := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(j).Get("districts").Getindex(a).Get("adcode").Tostring()
				// 获取行政区号
				LatitudeLongitude := gojson.Json(re.String()).Get("districts").Getindex(1).Get("districts").Getindex(i).Get("districts").Getindex(j).Get("districts").Getindex(a).Get("center").Tostring()
				ultimatelyMap[AdministrativeNumber] = LatitudeLongitude
				// 存储了经纬度和行政区号，行政区号作为key值,经纬度作为value值
			}

			 */
		}

	}
}

// MaptoStruct 将map转为结构体
type MaptoStruct struct {
	AdministrativeNumber string `json:"administrative_number"`
}

// Timer 每隔一个小时，轮询经纬度切片，通过它调用彩云接口
func Timer(Coordinates []string){
	// 一个小时调用一次这个接口
	ticker :=time.Tick(time.Hour)
	for _ = range ticker{
		QueryReqWeater(Coordinates)
	}
}
const filePath = "C:\\Users\\Administrator\\GolandProjects\\awesomeProject\\test2\\Gaode.txt"
const redirected ="C:\\Users\\Administrator\\GolandProjects\\awesomeProject\\test2\\1.txt"

func GetWeater(c *gin.Context){
	t1 :=time.Now()
	longitude :=c.PostForm("longitude")

	latitude :=c.PostForm("latitude")

	fmt.Println("longitude = ",longitude,"  latitude = ",latitude)
	f, err := strconv.ParseFloat(longitude, 32)
	f2,_:=strconv.ParseFloat(latitude,32)

	resRadiu, err := GlobalClient.GeoRadius("key123", f, f2, &redis.GeoRadiusQuery{
		Radius:      200,     // radius表示范围距离，
		Unit:        "km",   // 距离单位是 m|km|ft|mi
		WithCoord:   true,   // 传入WITHCOORD参数，则返回结果会带上匹配位置的经纬度
		WithDist:    true,   // 传入WITHDIST参数，则返回结果会带上匹配位置与给定地理位置的距离。
		WithGeoHash: false,  // 传入WITHHASH参数，则返回结果会带上匹配位置的hash值。
		Count:       1,      // 入COUNT参数，可以返回指定数量的结果。
		Sort:        "ASC",  // 默认结果是未排序的，传入ASC为从近到远排序，传入DESC为从远到近排序。
	}).Result()
	if err != nil {
		c.JSON(http.StatusOK,err)
	}

	if len(resRadiu)==0 {
		c.JSON(http.StatusOK,string("error"))
	}
	// 设置了Count参数，所以只会循环一次，不用考虑太多
	var gs string
	for _, i2 := range resRadiu {
		f1 := strconv.FormatFloat(i2.Longitude, 'f', -1, 32)
		f2 := strconv.FormatFloat(i2.Latitude, 'f', -1, 32)
		gs = f1 + "," + f2
		fmt.Println("f1 ============= ", f1, "================", f2)
		fmt.Println("gs ======================== ", gs)
		//val , _:=GlobalClient.Get(gs).Result()
	}
	WeatherTime :=reqMap[gs].WeatherData.times
	fmt.Println("*gs ==============================================",gs)
	if t1.Sub(WeatherTime)>=time.Minute*60 {
		// 如果大于=存储的时间，就同步请求
		fmt.Println("gs ======= ",gs)
		temp:= Segmentation(gs,",")
		updateWeater:= RequestWeather(temp[0],temp[1])
		reqMap[gs] = updateWeater
		c.JSON(http.StatusOK,updateWeater.WeatherData)
		return
	}
	c.JSON(http.StatusOK,reqMap[gs].WeatherData)

}
var reqMap map[string]WeatherCoordinates
func main() {
	initClient()

	f, _ := os.OpenFile(redirected, os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0755) // 将标准输出重定向到此处
	os.Stdout = f

	// ultimatelyMap := make(map[string]string, 2900)

	// Provincial(ultimatelyMap)
	// 新环境首次需要预加载此接口，获取到全国的行政单元，后续无需调用

	//MapToJsonDemo1(ultimatelyMap)		// 将map转为json，写入到指定文件中，后续无需调用

	ReadToMap := make(map[string]string, 500)   // 将全国行政区和经纬度从文件中读出到该map里
	ReadFromJson(ReadToMap)						// 反序列化 传入传出参数

	Coordinates :=QueryCoordinate(ReadToMap)
	// 通过行政区号拿经纬度

	QueryReqWeater (Coordinates)
	// 先请求一次天气数据，然后一个小时更新一次
	// reqMap := make(map[string]WeatherCoordinates,500)
	reqMap = make(map[string]WeatherCoordinates,500)
	for _, value := range Coordinates {
		// 遍历拿到的经纬度
		splices := Segmentation(value, ",")  // 由于是连在一起的，切割一下
		value = GetRedisGeo(splices[0],splices[1]) // 转储存一遍精度缺失的经纬度，也是连在一起的

		splices = Segmentation(value,",")
		data := RequestWeather(splices[0],splices[1])
		reqMap[splices[0]+","+splices[1]] = data
	}
	fmt.Println("reqMap = ",reqMap)
	// 用缺失的经纬度作为键，天气做为值

	// 从redis里面拿经纬度就行

	 //go Timer(Coordinates)
	r :=gin.Default()
	r.GET("/GetWeater",GetWeater)
	r.GET("/select",GetRedisWeater)
	r.POST("/select",QueryRedisWeater)
	r.Run(":8081")








}
